package com.group56.viewmodel;

import com.group56.model.dao.Impl.ScheduleDAOImpl;
import com.group56.model.dao.ScheduleDAO;
import com.group56.model.entity.Schedule;
import com.group56.utils.TimeTable;
import com.group56.view.coachend.schedule_module.ScheduleRectController;
import com.group56.viewmodel.dto.CoachScheduleListDTO;
import com.group56.viewmodel.dto.ScheduleDTO;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import lombok.NonNull;

import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CoachScheduleVM implements ViewModel{
    private static CoachScheduleVM coachScheduleVM;
    public static CoachScheduleVM getInstance(@NonNull String coachId) throws FileNotFoundException {
        if(coachScheduleVM == null || !coachId.equals(coachScheduleVM.scheduleListDTO.getCoachId())){
            coachScheduleVM = new CoachScheduleVM(coachId);
        }
        return coachScheduleVM;
    }
    public String coachId;
    public CoachScheduleListDTO getScheduleListDTO() {
        return scheduleListDTO;
    }

    public void setScheduleListDTO(CoachScheduleListDTO scheduleListDTO) {
        this.scheduleListDTO = scheduleListDTO;
    }

    private CoachScheduleListDTO scheduleListDTO;

    private final ScheduleDAO scheduleDAO = new ScheduleDAOImpl();

    //初始化ListDTO
    public CoachScheduleVM(String coachId) throws FileNotFoundException {
        this.coachId = coachId;
        updateFromModel();
//        //获取一串待筛选的schedule，TODO：DAO层可以新增一个查询更精确范围内schedule的方法
//        List<Schedule> scheduleList = scheduleDAO.query(coachId, "Coach");
//        //获取接下来五天的日期
//        SimpleDateFormat formatter= new SimpleDateFormat("yyyy.MM.dd");
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(new Date());
//        String today = formatter.format(calendar.getTime());
//        calendar.add(Calendar.DATE, 1);
//        String day1 = formatter.format(calendar.getTime());
//        calendar.add(Calendar.DATE, 1);
//        String day2 = formatter.format(calendar.getTime());
//        calendar.add(Calendar.DATE, 1);
//        String day3 = formatter.format(calendar.getTime());
//        calendar.add(Calendar.DATE, 1);
//        String day4 = formatter.format(calendar.getTime());
//        calendar.add(Calendar.DATE, 1);
//        String day5 = formatter.format(calendar.getTime());
//        this.scheduleListDTO = new CoachScheduleListDTO(today, coachId);
//        //在5天的list里预铺满unbooked/available的scheduleDTO
//        ObservableList<ScheduleDTO> scheduleDTOS1 = FXCollections.observableArrayList(new ArrayList<>());
//        for(int i=0; i<8; i++){
//            scheduleDTOS1.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day1)));
//        }
//        ObservableList<ScheduleDTO> scheduleDTOS2 = FXCollections.observableArrayList(new ArrayList<>());
//        for(int i=0; i<8; i++){
//            scheduleDTOS2.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day2)));
//        }
//        ObservableList<ScheduleDTO> scheduleDTOS3 = FXCollections.observableArrayList(new ArrayList<>());
//        for(int i=0; i<8; i++){
//            scheduleDTOS3.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day3)));
//        }
//        ObservableList<ScheduleDTO> scheduleDTOS4 = FXCollections.observableArrayList(new ArrayList<>());
//        for(int i=0; i<8; i++){
//            scheduleDTOS4.add(i, new ScheduleDTO(ScheduleRectController.STATUS.AVAILABLE, new Schedule(null,null,null, TimeTable.TIME[i], day4)));
//        }
//        ObservableList<ScheduleDTO> scheduleDTOS5 = FXCollections.observableArrayList(new ArrayList<>());
//        for(int i=0; i<8; i++){
//            scheduleDTOS5.add(i, new ScheduleDTO(ScheduleRectController.STATUS.AVAILABLE, new Schedule(null,null,null, TimeTable.TIME[i], day5)));
//        }
//        //如果有schedule就写入list
//        for(Schedule s : scheduleList){
//            if(s.getDate().equals(day1)){
//                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
//                if(s.getCustomerID().equals("-1"))
//                    status = ScheduleRectController.STATUS.UNAVAILABLE;
//                switch(s.getTime()){
//                    case "9:00-10:00":
//                        scheduleDTOS1.set(0,new ScheduleDTO(status, s));
//                        break;
//                    case "10:00-11:00":
//                        scheduleDTOS1.set(1,new ScheduleDTO(status, s));
//                        break;
//                    case "11:00-12:00":
//                        scheduleDTOS1.set(2,new ScheduleDTO(status, s));
//                        break;
//                    case "14:00-15:00":
//                        scheduleDTOS1.set(3,new ScheduleDTO(status, s));
//                        break;
//                    case "15:00-16:00":
//                        scheduleDTOS1.set(4,new ScheduleDTO(status, s));
//                        break;
//                    case "16:00-17:00":
//                        scheduleDTOS1.set(5,new ScheduleDTO(status, s));
//                        break;
//                    case "19:30-20:30":
//                        scheduleDTOS1.set(6,new ScheduleDTO(status, s));
//                        break;
//                    case "20:30-21:30":
//                        scheduleDTOS1.set(7,new ScheduleDTO(status, s));
//                        break;
//                }
//            }
//            if(s.getDate().equals(day2)){
//                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
//                if(s.getCustomerID().equals("-1"))
//                    status = ScheduleRectController.STATUS.UNAVAILABLE;
//                switch(s.getTime()) {
//                    case "9:00-10:00":
//                        scheduleDTOS2.set(0, new ScheduleDTO(status, s));
//                        break;
//                    case "10:00-11:00":
//                        scheduleDTOS2.set(1, new ScheduleDTO(status, s));
//                        break;
//                    case "11:00-12:00":
//                        scheduleDTOS2.set(2, new ScheduleDTO(status, s));
//                        break;
//                    case "14:00-15:00":
//                        scheduleDTOS2.set(3, new ScheduleDTO(status, s));
//                        break;
//                    case "15:00-16:00":
//                        scheduleDTOS2.set(4, new ScheduleDTO(status, s));
//                        break;
//                    case "16:00-17:00":
//                        scheduleDTOS1.set(5, new ScheduleDTO(status, s));
//                        break;
//                    case "19:30-20:30":
//                        scheduleDTOS2.set(6, new ScheduleDTO(status, s));
//                        break;
//                    case "20:30-21:30":
//                        scheduleDTOS2.set(7, new ScheduleDTO(status, s));
//                        break;
//                }
//            }
//            if(s.getDate().equals(day3)){
//                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
//                if(s.getCustomerID().equals("-1"))
//                    status = ScheduleRectController.STATUS.UNAVAILABLE;
//                switch(s.getTime()) {
//                    case "9:00-10:00":
//                        scheduleDTOS3.set(0, new ScheduleDTO(status, s));
//                        break;
//                    case "10:00-11:00":
//                        scheduleDTOS3.set(1, new ScheduleDTO(status, s));
//                        break;
//                    case "11:00-12:00":
//                        scheduleDTOS3.set(2, new ScheduleDTO(status, s));
//                        break;
//                    case "14:00-15:00":
//                        scheduleDTOS3.set(3, new ScheduleDTO(status, s));
//                        break;
//                    case "15:00-16:00":
//                        scheduleDTOS3.set(4, new ScheduleDTO(status, s));
//                        break;
//                    case "16:00-17:00":
//                        scheduleDTOS3.set(5, new ScheduleDTO(status, s));
//                        break;
//                    case "19:30-20:30":
//                        scheduleDTOS3.set(6, new ScheduleDTO(status, s));
//                        break;
//                    case "20:30-21:30":
//                        scheduleDTOS3.set(7, new ScheduleDTO(status, s));
//                        break;
//                }
//            }
//            if(s.getDate().equals(day4)){
//                switch(s.getTime()){
//                    case "9:00-10:00":
//                        scheduleDTOS4.set(0,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "10:00-11:00":
//                        scheduleDTOS4.set(1,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "11:00-12:00":
//                        scheduleDTOS4.set(2,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "14:00-15:00":
//                        scheduleDTOS4.set(3,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "15:00-16:00":
//                        scheduleDTOS4.set(4,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "16:00-17:00":
//                        scheduleDTOS4.set(5,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "19:30-20:30":
//                        scheduleDTOS4.set(6,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "20:30-21:30":
//                        scheduleDTOS4.set(7,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                }
//            }
//            if(s.getDate().equals(day5)){
//                switch(s.getTime()){
//                    case "9:00-10:00":
//                        scheduleDTOS5.set(0,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "10:00-11:00":
//                        scheduleDTOS5.set(1,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "11:00-12:00":
//                        scheduleDTOS5.set(2,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "14:00-15:00":
//                        scheduleDTOS5.set(3,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "15:00-16:00":
//                        scheduleDTOS5.set(4,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "16:00-17:00":
//                        scheduleDTOS5.set(5,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "19:30-20:30":
//                        scheduleDTOS5.set(6,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                    case "20:30-21:30":
//                        scheduleDTOS5.set(7,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
//                        break;
//                }
//            }
//        }
//        Map<StringProperty, ObservableList<ScheduleDTO>> map = new LinkedHashMap<>();
//        map.put(new SimpleStringProperty(day1), scheduleDTOS1);
//        map.put(new SimpleStringProperty(day2), scheduleDTOS2);
//        map.put(new SimpleStringProperty(day3), scheduleDTOS3);
//        map.put(new SimpleStringProperty(day4), scheduleDTOS4);
//        map.put(new SimpleStringProperty(day5), scheduleDTOS5);
//        ObservableMap<StringProperty, ObservableList<ScheduleDTO>> scheduleDTOMap = FXCollections.observableMap(map);
//        scheduleListDTO.setScheduleDTOMap(scheduleDTOMap);
    }

    @Override
    public void updateToModel() {
        AtomicInteger cnt= new AtomicInteger(0);
        scheduleListDTO.getScheduleDTOMap().forEach((key,scheduleDTOS)->{
            cnt.getAndIncrement();
            if(cnt.toString().equals("4")){
                for(ScheduleDTO scheduleDTO : scheduleDTOS){
                    if(scheduleDTO.getStatus()== ScheduleRectController.STATUS.UNAVAILABLE && scheduleDTO.getScheduleID()==null) {
                        scheduleDAO.insert(new Schedule("0", "-1", this.coachId, scheduleDTO.getTime(), scheduleDTO.getDate()));
                        System.out.println("insert");
                    }
                    if(scheduleDTO.getStatus()== ScheduleRectController.STATUS.AVAILABLE && scheduleDTO.getScheduleID()!=null){
                        scheduleDAO.delete(scheduleDTO.getScheduleID());
                        System.out.println("delete");
                    }
                }
            }
            if(cnt.toString().equals("5")){
                for(ScheduleDTO scheduleDTO : scheduleDTOS){
                    if(scheduleDTO.getStatus() == ScheduleRectController.STATUS.UNAVAILABLE && scheduleDTO.getScheduleID()==null) {
                        scheduleDAO.insert(new Schedule("0", "-1", this.coachId, scheduleDTO.getTime(), scheduleDTO.getDate()));
                        System.out.println("insert");
                    }
                    if(scheduleDTO.getStatus() == ScheduleRectController.STATUS.AVAILABLE && scheduleDTO.getScheduleID()!=null){
                        scheduleDAO.delete(scheduleDTO.getScheduleID());
                        System.out.println("delete"+scheduleDTO.getScheduleID());
                    }
                }
            }

        });
    }
    @Override
    public void updateFromModel(){
        //获取一串待筛选的schedule，TODO：DAO层可以新增一个查询更精确范围内schedule的方法
        List<Schedule> scheduleList = null;
        try {
            scheduleList = scheduleDAO.query(this.coachId, "Coach");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //获取接下来五天的日期
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy.MM.dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        String today = formatter.format(calendar.getTime());
        calendar.add(Calendar.DATE, 1);
        String day1 = formatter.format(calendar.getTime());
        calendar.add(Calendar.DATE, 1);
        String day2 = formatter.format(calendar.getTime());
        calendar.add(Calendar.DATE, 1);
        String day3 = formatter.format(calendar.getTime());
        calendar.add(Calendar.DATE, 1);
        String day4 = formatter.format(calendar.getTime());
        calendar.add(Calendar.DATE, 1);
        String day5 = formatter.format(calendar.getTime());
        this.scheduleListDTO = new CoachScheduleListDTO(today, coachId);
        //在5天的list里预铺满unbooked/available的scheduleDTO
        ObservableList<ScheduleDTO> scheduleDTOS1 = FXCollections.observableArrayList(new ArrayList<>());
        for(int i=0; i<8; i++){
            scheduleDTOS1.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day1)));
        }
        ObservableList<ScheduleDTO> scheduleDTOS2 = FXCollections.observableArrayList(new ArrayList<>());
        for(int i=0; i<8; i++){
            scheduleDTOS2.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day2)));
        }
        ObservableList<ScheduleDTO> scheduleDTOS3 = FXCollections.observableArrayList(new ArrayList<>());
        for(int i=0; i<8; i++){
            scheduleDTOS3.add(i, new ScheduleDTO(ScheduleRectController.STATUS.UNBOOKED, new Schedule(null,null,null, TimeTable.TIME[i], day3)));
        }
        ObservableList<ScheduleDTO> scheduleDTOS4 = FXCollections.observableArrayList(new ArrayList<>());
        for(int i=0; i<8; i++){
            scheduleDTOS4.add(i, new ScheduleDTO(ScheduleRectController.STATUS.AVAILABLE, new Schedule(null,null,null, TimeTable.TIME[i], day4)));
        }
        ObservableList<ScheduleDTO> scheduleDTOS5 = FXCollections.observableArrayList(new ArrayList<>());
        for(int i=0; i<8; i++){
            scheduleDTOS5.add(i, new ScheduleDTO(ScheduleRectController.STATUS.AVAILABLE, new Schedule(null,null,null, TimeTable.TIME[i], day5)));
        }
        //如果有schedule就写入list
        for(Schedule s : scheduleList){
            if(s.getDate().equals(day1)){
                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
                if(s.getCustomerID().equals("-1"))
                    status = ScheduleRectController.STATUS.UNAVAILABLE;
                switch(s.getTime()){
                    case "9:00-10:00":
                        scheduleDTOS1.set(0,new ScheduleDTO(status, s));
                        break;
                    case "10:00-11:00":
                        scheduleDTOS1.set(1,new ScheduleDTO(status, s));
                        break;
                    case "11:00-12:00":
                        scheduleDTOS1.set(2,new ScheduleDTO(status, s));
                        break;
                    case "14:00-15:00":
                        scheduleDTOS1.set(3,new ScheduleDTO(status, s));
                        break;
                    case "15:00-16:00":
                        scheduleDTOS1.set(4,new ScheduleDTO(status, s));
                        break;
                    case "16:00-17:00":
                        scheduleDTOS1.set(5,new ScheduleDTO(status, s));
                        break;
                    case "19:30-20:30":
                        scheduleDTOS1.set(6,new ScheduleDTO(status, s));
                        break;
                    case "20:30-21:30":
                        scheduleDTOS1.set(7,new ScheduleDTO(status, s));
                        break;
                }
            }
            if(s.getDate().equals(day2)){
                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
                if(s.getCustomerID().equals("-1"))
                    status = ScheduleRectController.STATUS.UNAVAILABLE;
                switch(s.getTime()) {
                    case "9:00-10:00":
                        scheduleDTOS2.set(0, new ScheduleDTO(status, s));
                        break;
                    case "10:00-11:00":
                        scheduleDTOS2.set(1, new ScheduleDTO(status, s));
                        break;
                    case "11:00-12:00":
                        scheduleDTOS2.set(2, new ScheduleDTO(status, s));
                        break;
                    case "14:00-15:00":
                        scheduleDTOS2.set(3, new ScheduleDTO(status, s));
                        break;
                    case "15:00-16:00":
                        scheduleDTOS2.set(4, new ScheduleDTO(status, s));
                        break;
                    case "16:00-17:00":
                        scheduleDTOS1.set(5, new ScheduleDTO(status, s));
                        break;
                    case "19:30-20:30":
                        scheduleDTOS2.set(6, new ScheduleDTO(status, s));
                        break;
                    case "20:30-21:30":
                        scheduleDTOS2.set(7, new ScheduleDTO(status, s));
                        break;
                }
            }
            if(s.getDate().equals(day3)){
                ScheduleRectController.STATUS status = ScheduleRectController.STATUS.BOOKED;
                if(s.getCustomerID().equals("-1"))
                    status = ScheduleRectController.STATUS.UNAVAILABLE;
                switch(s.getTime()) {
                    case "9:00-10:00":
                        scheduleDTOS3.set(0, new ScheduleDTO(status, s));
                        break;
                    case "10:00-11:00":
                        scheduleDTOS3.set(1, new ScheduleDTO(status, s));
                        break;
                    case "11:00-12:00":
                        scheduleDTOS3.set(2, new ScheduleDTO(status, s));
                        break;
                    case "14:00-15:00":
                        scheduleDTOS3.set(3, new ScheduleDTO(status, s));
                        break;
                    case "15:00-16:00":
                        scheduleDTOS3.set(4, new ScheduleDTO(status, s));
                        break;
                    case "16:00-17:00":
                        scheduleDTOS3.set(5, new ScheduleDTO(status, s));
                        break;
                    case "19:30-20:30":
                        scheduleDTOS3.set(6, new ScheduleDTO(status, s));
                        break;
                    case "20:30-21:30":
                        scheduleDTOS3.set(7, new ScheduleDTO(status, s));
                        break;
                }
            }
            if(s.getDate().equals(day4)){
                switch(s.getTime()){
                    case "9:00-10:00":
                        scheduleDTOS4.set(0,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "10:00-11:00":
                        scheduleDTOS4.set(1,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "11:00-12:00":
                        scheduleDTOS4.set(2,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "14:00-15:00":
                        scheduleDTOS4.set(3,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "15:00-16:00":
                        scheduleDTOS4.set(4,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "16:00-17:00":
                        scheduleDTOS4.set(5,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "19:30-20:30":
                        scheduleDTOS4.set(6,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "20:30-21:30":
                        scheduleDTOS4.set(7,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                }
            }
            if(s.getDate().equals(day5)){
                switch(s.getTime()){
                    case "9:00-10:00":
                        scheduleDTOS5.set(0,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "10:00-11:00":
                        scheduleDTOS5.set(1,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "11:00-12:00":
                        scheduleDTOS5.set(2,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "14:00-15:00":
                        scheduleDTOS5.set(3,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "15:00-16:00":
                        scheduleDTOS5.set(4,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "16:00-17:00":
                        scheduleDTOS5.set(5,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "19:30-20:30":
                        scheduleDTOS5.set(6,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                    case "20:30-21:30":
                        scheduleDTOS5.set(7,new ScheduleDTO(ScheduleRectController.STATUS.UNAVAILABLE, s));
                        break;
                }
            }
        }
        Map<StringProperty, ObservableList<ScheduleDTO>> map = new LinkedHashMap<>();
        map.put(new SimpleStringProperty(day1), scheduleDTOS1);
        map.put(new SimpleStringProperty(day2), scheduleDTOS2);
        map.put(new SimpleStringProperty(day3), scheduleDTOS3);
        map.put(new SimpleStringProperty(day4), scheduleDTOS4);
        map.put(new SimpleStringProperty(day5), scheduleDTOS5);
        ObservableMap<StringProperty, ObservableList<ScheduleDTO>> scheduleDTOMap = FXCollections.observableMap(map);
        scheduleListDTO.setScheduleDTOMap(scheduleDTOMap);


    }
}
